﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

// Data

namespace rFDevLib {
    public struct rFParam {
        public string name, comment, section;
        public int sectionNum; // If multiples of the same section occurs, this will increment for each new one. Will be -1 if unset
        public List<string> values;

        public rFParam( string line, string p_section = "", int p_sectionNum = -1 ) {
            name = string.Empty;
            comment = string.Empty;
            section = p_section;
            sectionNum = p_sectionNum;
            values = new List<string>();

            Parse( line );
        }

        public void Parse( string line ) {
            if ( line.Trim().Length == 0 ) return;
            if ( line.Trim().Substring( 0, 2 ) == "//" ) {
                // Only a comment
                comment = line.Substring( 2 ).Trim();
                return;
            }

            string[] mainCom = line.Split( new string[] { "//" }, StringSplitOptions.None );
            string[] parts = mainCom[0].Split( '=' );

            name = parts[0].Trim();
            if ( parts.Count() > 1 ) {
                parts[1] = parts[1].Trim();

                if ( parts[1].Substring( 0, 1 ) == "(" ) {
                    // Multiple values
                    string[] rawValues = parts[1].Replace( "(", "" ).Replace( ")", "" ).Split( ',' );

                    foreach ( string a in rawValues ) {
                        values.Add( a );
                    }
                } else {
                    // Single value
                    values.Add( parts[1] );
                }
            }

            if ( mainCom.Count() > 1 ) {
                // We have a comment!
                comment = mainCom.Last().Trim();
            }
        }

        public int GetInt( int i = 0 ) {
            if ( i + 1 > values.Count ) return 0;
            return int.Parse( values[i], CultureInfo.InvariantCulture );
        }
        public float GetFloat( int i = 0 ) {
            if ( i + 1 > values.Count ) return 0.0f;
            return float.Parse( values[i], CultureInfo.InvariantCulture );
        }
        public double GetDouble( int i = 0 ) {
            if ( i + 1 > values.Count ) return 0.0;
            return double.Parse( values[i], CultureInfo.InvariantCulture );
        }
        public string GetString( int i = 0 ) {
            if ( i + 1 > values.Count ) return string.Empty;
            return values[i];
        }

        public override string ToString() {
            if ( values == null ) return string.Empty;

            string ret = string.Empty;

            if ( values.Count > 1 ) {
                ret += name + "=(";
                for ( int i = 0; i < values.Count; i++ ) {
                    ret += values[i];
                    if ( i + 1 < values.Count ) ret += ",";
                }
                ret += ")";
            } else if ( values.Count == 1 ) {
                ret += name + "=" + values[0];
            }

            if ( comment.Length > 0 || ret.Length == 0 ) {
                ret += " // " + comment;
            }

            return ret.TrimStart();
        }
    }

    public class rFDataFile {
        public List<rFParam> m_params;

        public rFDataFile( string filePath = "NONE" ) {
            m_params = new List<rFParam>();
            if ( filePath != "NONE" ) 
                OpenFile( filePath );
        }

        public void Clear() {
            m_params = new List<rFParam>();
        }

        public void OpenFile( string filePath ) {
            StreamReader r = new StreamReader( filePath );
            string line;

            m_params.Clear();

            string category = string.Empty;
            int catNum = 0;

            List<string> CatNames = new List<string>();
            List<int> CatCounts = new List<int>();

            while ( r.EndOfStream == false ) {
                line = r.ReadLine();
                if ( line.Trim().Length == 0 ) {
                    // This line's empty, so is to be ignored.
                    // TODO: find a way to restart the loop here and now?
                } else if ( line.Trim().Substring(0, 1) == "[" ) {
                    // Category
                    int i = 1;
                    string c = string.Empty;
                    category = string.Empty;
                    while ( c != "]" ) {
                        category += c;
                        c = line.Trim().Substring( i, 1 );
                        i++;
                    }
                    //category = line.Trim().Substring( 1, line.Trim().Length - 2 );

                    bool found = false;
                    for ( i = 0; i < CatNames.Count; i++ ) {
                        if ( CatNames[i] == category ) {
                            CatCounts[i]++;
                            catNum = CatCounts[i];
                            found = true;
                            break;
                        }
                    }

                    if ( !found ) {
                        CatNames.Add( category );
                        CatCounts.Add( 1 );
                    }
                } else {
                    // Other params
                    m_params.Add( new rFParam( line.Trim(), category, catNum ) );
                }
            }

            r.Close();
        }

        public string ToString() {
            string Section = string.Empty;
            int SectionNum = -1;

            string Out = string.Empty;

            foreach ( rFParam a in m_params ) {
                if ( a.section.Length > 0 ) {
                    if ( a.section != Section ) {
                        Section = a.section;
                        SectionNum = a.sectionNum;
                        Out += "\n[" + Section + "]\n";
                    } else if ( a.sectionNum != SectionNum ) {
                        SectionNum = a.sectionNum;
                        Out += "\n[" + Section + "]\n";
                    }
                }
                Out += a.ToString() + "\n";
            }

            return Out;
        }
    }
}
